from rest_framework import serializers
from rest_framework.generics import GenericAPIView
from rest_framework.mixins import CreateModelMixin,ListModelMixin,RetrieveModelMixin, DestroyModelMixin,UpdateModelMixin

from api.serializers.asset_hosts import Hostserializer
from api.serializers.oauth import AssetsAdminSerializer
from utils.views import ChoiceAPIView
from utils.Mixins import  MultipleDestroyMixin

from asset.models import Host,Region
from oauth.models import Departments

from rest_framework.filters import SearchFilter, OrderingFilter
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.generics import ListAPIView
from rest_framework.pagination import PageNumberPagination

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status

from asset.tasks import task_host_collect
import copy

from django.conf import settings
from utils.sshops import SSH
import os
import json
from django.contrib.auth import get_user_model
Users = get_user_model()

from utils.custom_log   import log_start
logger = log_start('host')


class LargeResultsSetPagination(PageNumberPagination):
    page_size = 100  # 每页显示记录数，前端没有传入page_num，则默认显示此参数
    page_size_query_param = 'size' # 前端传入每页显示条数
    page_query_param = "page"  # 前端传入第几页
    max_page_size = 1000  # 后端控制每页显示最大记录数


class HostsMultipleDestroy(APIView):
    def delete(self,request, *args, **kwargs):
        delete_ids = self.request.query_params.get('ids', None)
        logger.info(f'批量删除id:{delete_ids}')
        if not delete_ids:
            return Response(data={'detail': '参数错误, ?ids=x,x 为必传参数'}, status=status.HTTP_400_BAD_REQUEST)
        delete_ids = delete_ids.split(',')
        del_queryset = Host.objects.filter(id__in=delete_ids)
        if len(delete_ids) != del_queryset.count():
            return Response(data={'detail': '删除数据不存在'}, status=status.HTTP_400_BAD_REQUEST)
        
        del_queryset.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)


class HostsViewSet(CreateModelMixin, ListModelMixin, GenericAPIView):
    """
    get:
    服务器--列表
    """
    queryset = Host.objects.all()
    serializer_class = Hostserializer
    pagination_class = LargeResultsSetPagination
    # 局部配置过滤类 们(全局配置用 DEFAULT_FILTER_BACKENDS)
    filter_backends = [SearchFilter, OrderingFilter,DjangoFilterBackend]
    # SearchFilter过滤类依赖的过滤条件 => 接口：/servers/?search=...
    search_fields = ['hostname', 'ip', 'instance_id','floatingip']
    # 局部配置过滤类依赖的过滤排序条件 => 接口：/servers/?ordering=...
    ordering_fields = ['id','hostname']
    # 字段过滤 => 接口 /servers/?region_id=3
    filterset_fields = ['region_id']

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)
        
    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)



class HostsDetailView(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin, GenericAPIView):
    """
    get:
    服务器--详情页
    
    """
    
    queryset = Host.objects.all()
    serializer_class = Hostserializer
    
    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)
    

class ServerStatusAPIView(ChoiceAPIView):
    """
    get:
    服务器--models类型列表

    服务器models中的类型列表信息, status: 200(成功), return: 服务器models中的类型列表
    """
    choice = Host.asset_status_choice

class ServerTypeAPIView(ChoiceAPIView):
    """
    get:
    服务器--models类型列表

    服务器models中的类型列表信息, status: 200(成功), return: 服务器models中的类型列表
    """
    choice = Host.asset_type_choice



class ServerIPListAPIView(APIView):
    """
    get:
    ip 列表
    
    IP 列表信息, status: 200(成功), return: 权限models中Department列表信息
    """
    def get(self, request):
        lst =  [ {'label': x.ip ,'value' : x.id } for x in Host.objects.all() ]
        return Response(data={'results':lst})


class ServerDepartmentListAPIView(APIView):
    """
    get:
    Department列表
    
    Department列表信息, status: 200(成功), return: 权限models中Department列表信息
    """
    def get(self, request):
        lst =  [ {'label': x.name ,'value' : x.id } for x in Departments.objects.all() ]
        return Response(data={'results':lst})

class ServerRegionListAPIView(APIView):
    """
    get:
    Region列表
    
    Region列表信息, status: 200(成功), return: 权限models中Region列表信息
    """
    def get(self, request):
        lst =  [ {'value' : x.id,'label' : x.region} for x in Region.objects.all() ]
        return Response(data={'results':lst})


class AssetsAdminListAPIView(ListAPIView):
    """
    get:
    资产--管理员查询

    资产管理员列表信息, status: 200(成功), return: 资产管理员列表信息
    """
    queryset = Users.objects.all()
    serializer_class = AssetsAdminSerializer
    filter_backends = (SearchFilter,)
    search_fields = ['username']



class HostCollectView(APIView):
    """
    get:
    服务器models中的类型列表信息, status: 200(成功), return: 采集当前主机硬件信息
    """
    def get(self, request):

        hostname = request.query_params.get('hostname')
        server = Host.objects.get(hostname=hostname)
        credential = server.ssh_id
        CLIENT_COLLECT_DIR = "/tmp/"   # 目标服务器脚本目录
        client_agent_name = "host_collect.py"   # 脚本名称

        local_file = os.path.join(settings.BASE_DIR, 'apps/asset', 'files', client_agent_name)
        logger.info (f'脚本路径: {local_file}')
        remote_file = os.path.join(CLIENT_COLLECT_DIR, client_agent_name)

        if server.connect_type == 1:
            ssh_ip=server.floatingip
        else:
            ssh_ip=server.ip

        ## 测试是否SSH连接成功
        if credential.authentication_type == 'Text':
            with SSH(
                ssh_ip, 
                credential.ssh_port,
                credential.ssh_user, 
                password=credential.password) as ssh:
                result = ssh.test()
            
        else:
            with SSH(
                ssh_ip,
                credential.ssh_port, 
                credential.ssh_user, 
                key=credential.private) as ssh:
                result = ssh.test()
                
        if result['code'] == 200:
            logger.error(f'[ {hostname}] 连通性测试 OK')
            result  = task_host_collect.delay (
                req=request.query_params,
                local_file=local_file,
                remote_file=remote_file,
                ssh_ip=ssh_ip
            )
            data = {'detail': f'异步更新中... ID:{result.id} [ {result.status} ] '}
            return Response(data=data)
        else:
            data = { 'detail': '主机配置同步失败,请检查连通性!' }
            return Response(data=data, status=status.HTTP_400_BAD_REQUEST) 